home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume3 / head < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  14.7 KB

  1. From: bene!luke!itkin
  2. Subject: head(1), and ctags(1) for AT&T type systems
  3. Reply-To: itkin@luke.UUCP (Steven List)
  4. Newsgroups: mod.sources
  5. Approved: jpn@panda.UUCP
  6.  
  7. Mod.sources:  Volume 3, Issue 87
  8. Submitted by: Steven List <bene!luke!itkin>
  9.  
  10.  
  11. # I've recently had the  pleasure  (?)  of  working  with  an  AT&T
  12. # 3B2/300.   Among  the  many  differences  I  encountered  are the
  13. # absences of the Berkeley  commands  head(1)  and  ctags(1).   I'd
  14. # gotten  used  to those command due to the generosity of Plexus in
  15. # providing them on their System III and V  systems.   Needless  to
  16. # say I immediately sat down and wrote them.
  17. # My version of head(1) adds a command line option to the standard:
  18. # +n.   In  this  case,  +n means "skip n lines before displaying".
  19. # Yes, I'm aware that I could use  sed(1)  for  this.   But  sed(1)
  20. # doesn't stop when it has done what you asked.  It still processes
  21. # to the end of file.  So, I figured that I'd  just  add  this  one
  22. # little feature.
  23. # My version of ctags(1) is pretty much the same  as  the  Berkeley
  24. # one,  as  far  as  I  can  tell.   It uses some code to recognize
  25. # function declarations that I borrowed from `cpr'  (I  don't  have
  26. # the  original author's name).  It is simple, straightforward, and
  27. # readily modified.
  28. # As always, comments, changes, and corrections are welcome.
  29. # Steven
  30. ###
  31. #  Steven List @ Benetics Corporation, Mt. View, CA
  32. #  Just part of the stock at "Uncle Bene's Farm"
  33. #  {cdp,engfocus,greipa,idi,oliveb,plx,sun,tolerant}!bene!luke!itkin
  34. ###
  35. #! /bin/sh
  36. # This is a shell archive, meaning:
  37. # 1. Remove everything above the #! /bin/sh line.
  38. # 2. Save the resulting text in a file.
  39. # 3. Execute the file with /bin/sh (not csh) to create the files:
  40. #    head.c
  41. #    ctags.c
  42. # This archive created: Sat Dec 14 17:38:46 1985
  43. export PATH; PATH=/bin:$PATH
  44. echo shar: extracting "'head.c'" '(4938 characters)'
  45. if test -f 'head.c'
  46. then
  47.     echo shar: will not over-write existing file "'head.c'"
  48. else
  49. sed 's/^ZZ//' << \SHAR_EOF > 'head.c'
  50. ZZ/* head - replace head command */
  51. ZZ/*
  52. ZZ * call: head [ +n ] [ -n ] [ file ... ]
  53. ZZ *
  54. ZZ *       +n = number of lines to skip before starting display
  55. ZZ *            default = 0
  56. ZZ *       -n = number of lines to display, starting with top of file
  57. ZZ *            default = 10
  58. ZZ *       file = any number of files may be present
  59. ZZ *                if name is `-', read from standard input
  60. ZZ */
  61. ZZ#include    <stdio.h>
  62. ZZ
  63. ZZ#define FALSE 0
  64. ZZ#define TRUE 1
  65. ZZ
  66. ZZvoid dofile ();
  67. ZZ
  68. ZZmain (ac, av)
  69. ZZint     ac;
  70. ZZchar    **av;
  71. ZZ{
  72. ZZ    register FILE *in = stdin;          /* default is standard input    */
  73. ZZ
  74. ZZ    register int header = FALSE;        /* TRUE if multiple files       */
  75. ZZ
  76. ZZ    register char *cp;                  /* general purpose pointer      */
  77. ZZ
  78. ZZ    register long nlines = 10;          /* number of lines to display   */
  79. ZZ    register long skip = 0;             /* number of lines to skip      */
  80. ZZ
  81. ZZ    register char *pgm;                 /* program name                 */
  82. ZZ
  83. ZZ    if (pgm = strrchr (av[0], '/')) pgm++;
  84. ZZ    else                            pgm = av[0];
  85. ZZ
  86. ZZ    /* ------------------------------------------------------------ */
  87. ZZ    /* Adjust args to skip program name                             */
  88. ZZ    /* ------------------------------------------------------------ */
  89. ZZ
  90. ZZ    av++; ac--;
  91. ZZ
  92. ZZ    /* ------------------------------------------------------------ */
  93. ZZ    /* process arguments/options                                    */
  94. ZZ    /*   it is assumed that the options will precede all file names */
  95. ZZ    /*   on the command line                                        */
  96. ZZ    /* ------------------------------------------------------------ */
  97. ZZ
  98. ZZ    while (ac)
  99. ZZ    {
  100. ZZ        if (*av[0] == '+')              /* lines to skip            */
  101. ZZ        {
  102. ZZ            skip = atoi (&av[0][1]);
  103. ZZ            ac--; av++;
  104. ZZ        }
  105. ZZ        else if (*av[0] == '-')         /* lines to display         */
  106. ZZ        {
  107. ZZ            nlines = atoi (&av[0][1]);
  108. ZZ            ac--; av++;
  109. ZZ        }
  110. ZZ        else break;
  111. ZZ    }
  112. ZZ
  113. ZZ    /* ------------------------------------------------------------ */
  114. ZZ    /* If any files, then process each                              */
  115. ZZ    /* ------------------------------------------------------------ */
  116. ZZ
  117. ZZ    if (ac)
  118. ZZ    {
  119. ZZ    /* ------------------------------------------------------------ */
  120. ZZ    /* If more than one file name specified, display headers        */
  121. ZZ    /* ------------------------------------------------------------ */
  122. ZZ
  123. ZZ        header = ac > 1;
  124. ZZ        while (ac--)
  125. ZZ        {
  126. ZZ            if (!strcmp (*av, "-"))
  127. ZZ            {
  128. ZZ                dofile (stdin, "standard input", skip, nlines, header);
  129. ZZ            }
  130. ZZ            else if (!(in = fopen (*av, "r")))
  131. ZZ            {
  132. ZZ                fprintf (stderr,
  133. ZZ                    "head: cannot read file %s - skipping\n", *av);
  134. ZZ            }
  135. ZZ            else
  136. ZZ            {
  137. ZZ                dofile (in, *av, skip, nlines, header);
  138. ZZ                fclose (in);
  139. ZZ            }
  140. ZZ            av++;
  141. ZZ        }
  142. ZZ    }
  143. ZZ    else dofile (stdin, "standard input", skip, nlines, FALSE);
  144. ZZ
  145. ZZ    exit (0);
  146. ZZ}
  147. ZZ/* ------------------------------------------------------------ */
  148. ZZ/* Process a file, skipping and displaying as necessary         */
  149. ZZ/* ------------------------------------------------------------ */
  150. ZZvoid
  151. ZZdofile (in, inname, skip, nlines, dohead)
  152. ZZregister FILE *in;          /* input stream                         */
  153. ZZregister char *inname;      /* input file name                      */
  154. ZZregister long skip;         /* number of lines to skip              */
  155. ZZregister long nlines;       /* number of lines to display           */
  156. ZZ         int dohead;        /* TRUE if header is to be displayed    */
  157. ZZ{
  158. ZZ    register char *c;           /* convenient local pointer         */
  159. ZZ    register long lineno = 0;   /* line number in file              */
  160. ZZ
  161. ZZ    char    inbuf[1024];        /* line buffer                      */
  162. ZZ
  163. ZZ    /* ------------------------------------------------------------ */
  164. ZZ    /* Print header if necessary                                    */
  165. ZZ    /* ------------------------------------------------------------ */
  166. ZZ
  167. ZZ    if (dohead)
  168. ZZ    {
  169. ZZ        printf ("\
  170. ZZ+-----------------------------------------------------------------+\n\
  171. ZZ+                %-40.40s         +\n\
  172. ZZ+-----------------------------------------------------------------+\n",
  173. ZZ            inname);
  174. ZZ    }
  175. ZZ
  176. ZZ    /* ------------------------------------------------------------ */
  177. ZZ    /* Skip lines                                                   */
  178. ZZ    /* ------------------------------------------------------------ */
  179. ZZ
  180. ZZ    while (lineno++ < skip && fgets (inbuf, sizeof inbuf, in));
  181. ZZ
  182. ZZ    /* ------------------------------------------------------------ */
  183. ZZ    /* Display lines                                                */
  184. ZZ    /* ------------------------------------------------------------ */
  185. ZZ
  186. ZZ    lineno = 0;
  187. ZZ
  188. ZZ    while (lineno++ < nlines && fgets (inbuf, sizeof inbuf, in))
  189. ZZ        fputs (inbuf, stdout);
  190. ZZ    
  191. ZZ    return;
  192. ZZ}
  193. SHAR_EOF
  194. if test 4938 -ne "`wc -c < 'head.c'`"
  195. then
  196.     echo shar: error transmitting "'head.c'" '(should have been 4938 characters)'
  197. fi
  198. fi # end of overwriting check
  199. echo shar: extracting "'ctags.c'" '(6771 characters)'
  200. if test -f 'ctags.c'
  201. then
  202.     echo shar: will not over-write existing file "'ctags.c'"
  203. else
  204. sed 's/^ZZ//' << \SHAR_EOF > 'ctags.c'
  205. ZZ/*T ctags - generate VI tags file from C sources */
  206. ZZ/*S globals and stuff */
  207. ZZ#include    <stdio.h>
  208. ZZ#include    <ctype.h>
  209. ZZ
  210. ZZ#define EQ ==
  211. ZZ#define NE !=
  212. ZZ#define GT >
  213. ZZ#define GE >=
  214. ZZ#define LT <
  215. ZZ#define LE <=
  216. ZZ#define OR ||
  217. ZZ#define AND &&
  218. ZZ
  219. ZZ#define TRUE 1
  220. ZZ#define FALSE 0
  221. ZZ
  222. ZZ#define SPACE ' '
  223. ZZ#define NUL '\0'
  224. ZZ
  225. ZZtypedef short   BOOL;
  226. ZZ
  227. ZZchar    FunctionName[40];
  228. ZZ
  229. ZZchar    *ReservedWord[]  = { 
  230. ZZ     "BOOL", "auto", "bool", "break", "case", "char", "continue",
  231. ZZ     "default", "do", "double", "else", "entry", "enum",
  232. ZZ     "extern", "float", "for", "goto", "if",
  233. ZZ     "int", "long", "register", "return", "short",
  234. ZZ     "sizeof", "static", "struct", "switch",
  235. ZZ     "typedef", "union", "unsigned", "void", "while",
  236. ZZ     NULL };
  237. ZZ
  238. ZZchar    *pgm;
  239. ZZchar    inbuf[512];
  240. ZZ
  241. ZZextern char *strchr ();            /* index on BSD                        */
  242. ZZextern char *strrchr ();        /* rindex on BSD                    */
  243. ZZextern char *strpbrk ();        /* ???                                */
  244. ZZ
  245. ZZint     skiptoend ();            /* skip to end of function            */
  246. ZZchar    ckfunc ();                /* check for function declaration    */
  247. ZZ/*Page Eject*/
  248. ZZmain (ac, av)
  249. ZZint        ac;
  250. ZZchar    *av[];
  251. ZZ{
  252. ZZ    register FILE *in;            /* input file stream                */
  253. ZZ    register FILE *tagfile;        /* `tags' file being created        */
  254. ZZ
  255. ZZ    register char *cp;            /* convenient character pointers    */
  256. ZZ    register char *ep;            /*                                    */
  257. ZZ
  258. ZZ    register int i;                    /* loop index and such            */
  259. ZZ    register int index = FALSE;        /* if true, produce a functions    */
  260. ZZ                                    /* index instead of tags file    */
  261. ZZ    register int line_number = 0;    /* line number of declaration    */
  262. ZZ    register int optind = 1;        /* like getopt - command arg    */
  263. ZZ
  264. ZZ    char    *funcname;                /* function name                */
  265. ZZ
  266. ZZ    char    filename[15];            /* like it says                    */
  267. ZZ
  268. ZZ    if (pgm = strrchr (av[0], '/')) pgm++;
  269. ZZ    else                             pgm = av[0];
  270. ZZ
  271. ZZ    /* ------------------------------------------------------------ */
  272. ZZ    /* Create the tags file                                         */
  273. ZZ    /* ------------------------------------------------------------ */
  274. ZZ
  275. ZZ    tagfile = fopen ("tags", "w");
  276. ZZ    if (!tagfile)
  277. ZZ    {
  278. ZZ        perror ("tags");
  279. ZZ        fprintf (stderr,
  280. ZZ            "%s: cannot create file tags\n", pgm);
  281. ZZ        exit (1);
  282. ZZ    }
  283. ZZ
  284. ZZ    /* ------------------------------------------------------------ */
  285. ZZ    /* If selected, write a function index to stdout instead        */
  286. ZZ    /* ------------------------------------------------------------ */
  287. ZZ
  288. ZZ    if (!strncmp (av[1], "-x", 2))
  289. ZZ    {
  290. ZZ        index = TRUE;
  291. ZZ        optind++;
  292. ZZ    }
  293. ZZ
  294. ZZ    /* ------------------------------------------------------------ */
  295. ZZ    /* Process each file specified on the command line              */
  296. ZZ    /* ------------------------------------------------------------ */
  297. ZZ
  298. ZZ    for (i = optind; i LT ac; i++)
  299. ZZ    {
  300. ZZ        if (!(in = fopen (av[i], "r")))
  301. ZZ        {
  302. ZZ            perror (av[i]);
  303. ZZ            fprintf (stderr,
  304. ZZ                "%s: unable to read file %s\n", pgm, av[i]);
  305. ZZ        }
  306. ZZ        else
  307. ZZ        {
  308. ZZ            while (fgets (inbuf, sizeof inbuf, in))
  309. ZZ            {
  310. ZZ                line_number++;
  311. ZZ                if (ckfunc (inbuf))
  312. ZZ                {
  313. ZZ    /* ------------------------------------------------------------ */
  314. ZZ    /* Found a function declaration                                 */
  315. ZZ    /* ------------------------------------------------------------ */
  316. ZZ
  317. ZZ                    inbuf[strlen(inbuf)-1] = NUL;
  318. ZZ                    if (index)
  319. ZZ                    {
  320. ZZ                        printf ("%-20.20s  %6d  %s\t%s\n",
  321. ZZ                            FunctionName, line_number, av[i], inbuf);
  322. ZZ                    }
  323. ZZ    /* ------------------------------------------------------------ */
  324. ZZ    /* Special case function name `main'                            */
  325. ZZ    /* ------------------------------------------------------------ */
  326. ZZ                    else if (!strcmp (FunctionName, "main"))
  327. ZZ                    {
  328. ZZ                        cp = strrchr (av[i], '/');
  329. ZZ                        if (cp) cp++;
  330. ZZ                        else cp = av[i];
  331. ZZ                        strcpy (filename, cp);
  332. ZZ                        ep = strrchr (filename, '.');
  333. ZZ                        if (ep) *ep = NUL;
  334. ZZ                        fprintf (tagfile, "M%s\t%s\t?^%s$?\n",
  335. ZZ                            filename, av[i], inbuf);
  336. ZZ                    }
  337. ZZ                    else
  338. ZZ                    {
  339. ZZ                        fprintf (tagfile, "%s\t%s\t?^%s$?\n",
  340. ZZ                            FunctionName, av[i], inbuf);
  341. ZZ                    }
  342. ZZ                    line_number += skiptoend (in);
  343. ZZ                }
  344. ZZ            }
  345. ZZ            fclose (in);
  346. ZZ        }
  347. ZZ    }
  348. ZZ    fclose (tagfile);
  349. ZZ
  350. ZZ    /* ------------------------------------------------------------ */
  351. ZZ    /* Tags file must be sorted alphabetically on tag               */
  352. ZZ    /* ------------------------------------------------------------ */
  353. ZZ
  354. ZZ    system ("sort -u -t'\t' +0 -1 -o tags tags");
  355. ZZ
  356. ZZ    exit (0);
  357. ZZ}
  358. ZZ/*S ckfunc - check line for function declaration */
  359. ZZ/*H ckfunc */
  360. ZZ/*E*/
  361. ZZ
  362. ZZ#define isidchr(c) (isalnum(c) OR (c EQ '_'))
  363. ZZ
  364. ZZchar
  365. ZZckfunc (s)
  366. ZZregister char   *s;                /* string to check for declaration    */
  367. ZZ{
  368. ZZ    register char *p;            /* convenient character pointer        */
  369. ZZ    register int  i;            /* useful loop index                 */
  370. ZZ    register int  result;        /* used to terminate search loop    */
  371. ZZ    register char found = FALSE;    /* true if declaration found    */
  372. ZZ
  373. ZZ    static char *_fnm = "ckfunc";
  374. ZZ
  375. ZZ    /* ------------------------------------------------------------ */
  376. ZZ    /* There's GOT to be a left paren for there to be a declaration */
  377. ZZ    /* ------------------------------------------------------------ */
  378. ZZ
  379. ZZ    if (strchr (s, '('))
  380. ZZ    {
  381. ZZ        found = TRUE;
  382. ZZ
  383. ZZ        while (found)
  384. ZZ        {
  385. ZZ            found = FALSE;
  386. ZZ            p = FunctionName;
  387. ZZ            for (s; isascii (*s) AND isspace (*s) AND *s; s++);
  388. ZZ            if( *s EQ '*' )
  389. ZZ            {
  390. ZZ                for (++s; isascii (*s) AND isspace (*s) AND *s; s++);
  391. ZZ            }
  392. ZZ
  393. ZZ            if ((*s EQ '_') OR isalpha(*s))
  394. ZZ            {
  395. ZZ                while (isidchr (*s)) *p++ = *s++;
  396. ZZ
  397. ZZ                *p = NUL;
  398. ZZ
  399. ZZ                for (found = FALSE, i = 0;
  400. ZZ                     !found AND ReservedWord[i]; i++)
  401. ZZ                {
  402. ZZ                    if (!(result = strcmp (FunctionName, ReservedWord[i])))
  403. ZZ                        found = TRUE;
  404. ZZ                    else if  (result LT 0) break;
  405. ZZ                }
  406. ZZ            }
  407. ZZ        }
  408. ZZ    }
  409. ZZ    
  410. ZZ    for (s; isascii (*s) AND isspace (*s) AND *s; s++);
  411. ZZ
  412. ZZ    if (*s EQ '(')
  413. ZZ    {
  414. ZZ        for (found = FALSE; *s AND !found; s++)
  415. ZZ            found = *s EQ ')';
  416. ZZ        
  417. ZZ        if (found)
  418. ZZ        {
  419. ZZ            for (; *s AND isspace (*s); s++);
  420. ZZ
  421. ZZ            found = *s NE ';';
  422. ZZ        }
  423. ZZ    }
  424. ZZ
  425. ZZ    return found;
  426. ZZ}
  427. ZZ/* ------------------------------------------------------------ */
  428. ZZ/* Skiptoend is called after a function declaration is found    */
  429. ZZ/* to skip to the end of the function.                          */
  430. ZZ/* ------------------------------------------------------------ */
  431. ZZint
  432. ZZskiptoend (in)
  433. ZZregister FILE *in;            /* file being processed                    */
  434. ZZ{
  435. ZZ    register int nest = 0;        /* nesting level - zero means end    */
  436. ZZ    register int c;                /* character being checked            */
  437. ZZ    register int line_number = 0;    /* like it says                    */
  438. ZZ
  439. ZZ    /* ------------------------------------------------------------ */
  440. ZZ    /* Simpleminded search for the starting brace                   */
  441. ZZ    /* ------------------------------------------------------------ */
  442. ZZ
  443. ZZ    while (((c = getc (in)) NE EOF) AND c NE '{')
  444. ZZ        if (c EQ '\n') line_number++;
  445. ZZ
  446. ZZ    nest++;
  447. ZZ
  448. ZZ    /* ------------------------------------------------------------ */
  449. ZZ    /* Keep going until the paired brace is found                   */
  450. ZZ    /* ------------------------------------------------------------ */
  451. ZZ
  452. ZZ    while (nest AND ((c = getc (in)) NE EOF))
  453. ZZ    {
  454. ZZ        switch (c)
  455. ZZ        {
  456. ZZ            case    '{':    nest++; break;
  457. ZZ            case    '}':    nest--; break;
  458. ZZ            case    '\n':    line_number++;
  459. ZZ        }
  460. ZZ    }
  461. ZZ
  462. ZZ    return line_number;
  463. ZZ}
  464. SHAR_EOF
  465. if test 6771 -ne "`wc -c < 'ctags.c'`"
  466. then
  467.     echo shar: error transmitting "'ctags.c'" '(should have been 6771 characters)'
  468. fi
  469. fi # end of overwriting check
  470. #    End of shell archive
  471. exit 0
  472.  
  473.  
  474.  
  475.